package com.sea.base.utils

import android.annotation.SuppressLint
import androidx.lifecycle.Lifecycle
import com.sea.base.ext.obs.doOnDestroyed
import java.util.*

/**
 * Author: Wu Chang
 * 计时的工具
 * Date: 2023/11/15 13:25
 */
class TimerSecondKt(
    private var terminate: Int,
    /** 计时的最终值 单位 秒 如果 isReverse=false && terminate=0 则表示上不封顶的计时**/
    private val period: Long,
    /** 计时间续 单位 毫秒 **/
    private val timerCall: (Int) -> Unit,
    /** 计时回调 **/
    private val over: () -> Unit,
    /** 结束回调 **/
    private val isReverse: Boolean = false,
    /** 是否倒叙 **/
) {

    private var start = if (isReverse) terminate else 0

    private var reckon = 0

    private var timer: Timer? = null
    private var timerTask: TimerTask? = null

    private var running = false

    private var lifecycle: Lifecycle? = null

    fun with(lifecycle: Lifecycle): TimerSecondKt {
        this.lifecycle = lifecycle
        return this
    }

    fun start() {
        stop()
        reckon = start
        running = true
        timerTask = object : TimerTask() {
            @SuppressLint("SetTextI18n")
            override fun run() {
                timerCall.invoke(reckon)
                changed()
            }
        }

        lifecycle?.doOnDestroyed {
            stop()
        }

        timer = Timer()
        timer?.schedule(timerTask, 0, period)
    }

    fun stop() {
        running = false
        timer?.cancel()
        timerTask?.cancel()
        timerTask = null
        timer = null
    }

    private fun changed() {
        if (isReverse) {
            reckon -= (period / 1000).toInt()
            if (reckon < 0) {
                stop()
                over.invoke()
            }
        } else {
            reckon += (period / 1000).toInt()
            // 增长计时且 terminate==0 的时候，表示计时不会结束
            if (terminate in 1 until reckon) {
                stop()
                over.invoke()
            }
        }
    }

    fun isRunning(): Boolean {
        return running
    }

    /**
     * 刷新计时
     */
    fun resetTime(terminate: Int) {
        this.terminate = terminate
        start = if (isReverse) terminate else 0
        if (isRunning()) {
            stop()
        }
        start()
    }
}